package com.xinzhidi.web.onlineMonitor.service;

import cn.hutool.core.thread.ThreadUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.xinzhidi.common.constant.AgreementConstants;
import com.xinzhidi.common.core.page.TableDataInfo;
import com.xinzhidi.common.exception.ServiceException;
import com.xinzhidi.common.utils.DateUtils;
import com.xinzhidi.common.utils.ThreadPoolUtil;
import com.xinzhidi.web.ctw.service.HouseholdTemperatureService;
import com.xinzhidi.web.equipment.domain.Equipment;
import com.xinzhidi.web.equipment.service.EquipmentService;
import com.xinzhidi.web.netty.entity.AgreementCommand;
import com.xinzhidi.web.netty.entity.DeviceInstruction;
import com.xinzhidi.web.netty.entity.dto.AgreementHeatListDto;
import com.xinzhidi.web.netty.entity.dto.AgreementSeahorseValveListDto;
import com.xinzhidi.web.netty.entity.dto.AgreementUnitValveListDto;
import com.xinzhidi.web.netty.service.*;
import com.xinzhidi.web.netty.utils.FormatData;
import com.xinzhidi.web.netty.utils.HexadecimalUtil;
import com.xinzhidi.web.onlineMonitor.domain.FieldSort;
import com.xinzhidi.web.onlineMonitor.domain.po.MeterReadPo;
import com.xinzhidi.web.onlineMonitor.domain.po.OnlineMonitorPo;
import com.xinzhidi.web.onlineMonitor.domain.vo.OnlineMonitorVo;
import com.xinzhidi.web.onlineMonitor.mapper.OnlineMonitorMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;


/**
 * 在线监测Service业务层处理
 *
 * @author cx
 * @date 2023-06-09
 */
@Service
@RequiredArgsConstructor
@Lazy
@Slf4j
public class OnlineMonitorService {

    private final OnlineMonitorMapper monitorMapper;

    private final AgreementCommandService agreementCommandService;

    private final AgreementHeatService heatService;

    private final DeviceInstructionService deviceInstructionService;

    private final AgreementUnitValveService UnitValveService;

    private final HouseholdTemperatureService temperatureService;

    private final AgreementSeahorseValveService seahorseValveService;

    private final AgreementUnitValveService unitValveService;

    private final EquipmentService equipmentService;

    @Autowired
    private ThreadPoolUtil threadPoolUtil;

    @Autowired
    private OnlineMonitorService monitorService;

    /**
     * 在线监测-楼栋列表
     *
     * @param po 查询条件
     * @return 列表
     */
    public TableDataInfo<OnlineMonitorVo> listBuild(OnlineMonitorPo po) {
        String tableField = getTableField(po);
        if (tableField != null) {
            po.setTableField(tableField);
        }
        List<OnlineMonitorVo> list = monitorMapper.listBuild(po);
        if (CollectionUtils.isEmpty(list)) {
            return TableDataInfo.getDataTable(list);
        }
        OnlineMonitorVo monitorVo;
        for(OnlineMonitorVo vo : list){
            if(vo.getPlotId() == 36){
                System.out.println(111);
            }
//            monitorVo = monitorMapper.getBuildIndex(vo.getBuildId());
//            if(monitorVo != null){
//                vo.setThermalPower(monitorVo.getThermalPower());
//                vo.setVelocityFlow(monitorVo.getVelocityFlow());
//                vo.setWaterSupplyTemperature(monitorVo.getWaterSupplyTemperature());
//                vo.setReturnWaterTemperature(monitorVo.getReturnWaterTemperature());
//                vo.setTotalFlow(monitorVo.getTotalFlow());
//                vo.setCurrentHeatOrCold(monitorVo.getCurrentHeatOrCold());
//                vo.setThermalCreateTime(monitorVo.getThermalCreateTime());
//                if(monitorVo.getValveCrateTime() != null){
//                    vo.setSetOpen(monitorVo.getSetOpen());
//                    vo.setValveCrateTime(monitorVo.getValveCrateTime());
//                }else{
//                    vo.setSetOpen(null);
//                }
//            }
        }

        if (tableField == null) {
            // 使用自定义比较器对列表进行排序
            Collections.sort(list, new OnLineComparator());
        }

//        List<AgreementHeat> heatList;
//        List<AgreementUnitValve> unitValveList;
//        LambdaQueryWrapper<AgreementHeat> heatWrapper;
//        LambdaQueryWrapper<AgreementUnitValve> unitValveWrapper;
//        for (OnlineMonitorVo vo : list) {
//            //获取楼栋下的热量表抄表时间
//            heatWrapper = Wrappers.lambdaQuery(AgreementHeat.class)
//                    .eq(AgreementHeat::getBuildId, vo.getBuildId());
//            heatList = heatService.list(heatWrapper);
//            if (CollectionUtils.isEmpty(heatList)) {
//                continue;
//            }
//            List<Date> dateTimeList = heatList.stream().map(AgreementHeat::getCreateTime).collect(Collectors.toList());
//            vo.setThermalCreateTime(DateUtils.calculateAverageDate(dateTimeList));
//
//            //获取楼栋下的阀门抄表时间
//            unitValveWrapper = Wrappers.lambdaQuery(AgreementUnitValve.class)
//                    .eq(AgreementUnitValve::getBuildId, vo.getBuildId());
//            unitValveList = unitValveService.list(unitValveWrapper);
//            if (CollectionUtils.isEmpty(unitValveList)) {
//                continue;
//            }
//            List<Date> unitValveTimeList = unitValveList.stream().map(AgreementUnitValve::getCreateTime).collect(Collectors.toList());
//            vo.setValveCrateTime(DateUtils.calculateAverageDate(unitValveTimeList));
//        }
        return TableDataInfo.getDataTable(list);
    }

    public class OnLineComparator implements Comparator<OnlineMonitorVo> {

        @Override
        public int compare(OnlineMonitorVo o1, OnlineMonitorVo o2) {
            // 从'name'字段中提取数字并进行比较
            int num1 = com.xinzhidi.common.utils.StringUtils.getInteger(o1.getBuildName());
            int num2 = com.xinzhidi.common.utils.StringUtils.getInteger(o2.getBuildName());
            return Integer.compare(num1, num2);
        }
    }

    /**
     * 在线监测-单元列表
     *
     * @param po 查询条件
     * @return 列表
     */
    public TableDataInfo<OnlineMonitorVo> listBuildUnit(OnlineMonitorPo po) {
        String tableField = getTableField(po);
        if (tableField != null) {
            po.setTableField(tableField);
        }
        List<OnlineMonitorVo> list = monitorMapper.listBuildUnit(po);
        if (!CollectionUtils.isEmpty(list)) {
            List<Equipment> equipmentList;
            //阀门设备编号集合
            List<String> valveEquipmentList;
            //热量表设备编号集合
            List<String> heatEquipmentList;
            OnlineMonitorVo monitorVo;

            for (OnlineMonitorVo vo : list) {
                //通过历史数据表获取指标数据
                monitorVo = monitorMapper.getBuildUnitIndex(vo.getUnitId());
                if (monitorVo != null) {
                    vo.setThermalPower(monitorVo.getThermalPower());
                    vo.setVelocityFlow(monitorVo.getVelocityFlow());
                    vo.setWaterSupplyTemperature(monitorVo.getWaterSupplyTemperature());
                    vo.setReturnWaterTemperature(monitorVo.getReturnWaterTemperature());
                    vo.setTotalFlow(monitorVo.getTotalFlow());
                    vo.setCurrentHeatOrCold(monitorVo.getCurrentHeatOrCold());
                    vo.setThermalCreateTime(monitorVo.getThermalCreateTime());
                }
                equipmentList = equipmentService.list(Wrappers.lambdaQuery(Equipment.class)
                        .eq(Equipment::getUnitId, vo.getUnitId())
                        .eq(Equipment::getEquipmentLevel, AgreementConstants.DataType.BUILD_UNIT));
                if (CollectionUtils.isEmpty(equipmentList)) {
                    continue;
                }
                valveEquipmentList = equipmentList.stream()
                        .filter(equipment -> equipment.getProtocolType().equals(AgreementConstants.AgreementType.UNIT_VALVE))
                        .map(Equipment::getEquipmentCode)
                        .collect(Collectors.toList());
                heatEquipmentList = equipmentList.stream()
                        .filter(equipment -> equipment.getProtocolType().equals(AgreementConstants.AgreementType.UNIT_HEAT_METER))
                        .map(Equipment::getEquipmentCode)
                        .collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(valveEquipmentList)) {
                    vo.setValveCode(valveEquipmentList);
                }
                if (!CollectionUtils.isEmpty(heatEquipmentList)) {
                    vo.setHeatCode(heatEquipmentList);
                }



            }
        }
        return TableDataInfo.getDataTable(list);
    }

    public TableDataInfo<OnlineMonitorVo> listHousehold(OnlineMonitorPo po) {
        String tableField = getTableField(po);
        if (tableField != null) {
            po.setTableField(tableField);
        }
        List<OnlineMonitorVo> list = monitorMapper.listHousehold(po);
        if (!CollectionUtils.isEmpty(list)) {
            List<Equipment> equipmentList;
            //阀门设备编号集合
            List<String> valveEquipmentList;
            //热量表设备编号集合
            List<String> heatEquipmentList;
            OnlineMonitorVo monitorVo;
            for (OnlineMonitorVo vo : list) {

//                monitorVo = monitorMapper.getHouseholdIndex(vo.getHouseholdId());

                equipmentList = equipmentService.list(Wrappers.lambdaQuery(Equipment.class)
                        .eq(Equipment::getHouseholdId, vo.getHouseholdId()));
                if (CollectionUtils.isEmpty(equipmentList)) {
                    continue;
                }
                valveEquipmentList = equipmentList.stream()
                        .filter(equipment -> equipment.getProtocolType().equals(AgreementConstants.AgreementType.HOUSEHOLD_VALVE)
                                || equipment.getProtocolType().equals(AgreementConstants.AgreementType.SEAHORSE_VALVE_METER))
                        .map(Equipment::getEquipmentCode)
                        .collect(Collectors.toList());
                heatEquipmentList = equipmentList.stream()
                        .filter(equipment -> equipment.getProtocolType().equals(AgreementConstants.AgreementType.HOUSEHOLD_HEAT_METER))
                        .map(Equipment::getEquipmentCode)
                        .collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(valveEquipmentList)) {
                    vo.setValveCode(valveEquipmentList);
                }
                if (!CollectionUtils.isEmpty(heatEquipmentList)) {
                    vo.setHeatCode(heatEquipmentList);
                }
            }
        }
        return TableDataInfo.getDataTable(list);
    }

    // 根据请求的类型返回字段排序
    public String getTableField(OnlineMonitorPo po) {
        for (FieldSort sort : FieldSort.values()) {
            if (Objects.equals(sort.getType(), po.getFieldNumber())) {
                return sort.getTableField();
            }
        }
        return null;
    }

    /**
     * 抄表
     *
     * @param businessType 指令业务类型
     * @param list
     */
    public void meterRead(Integer businessType, List<MeterReadPo> list) throws InterruptedException {

        Set<String> types = list.stream().map(MeterReadPo::getType).collect(Collectors.toSet());
//        if (types.contains("1")) {
//            return;
//        }
        //总数据（需发送的指令）
        List<DeviceInstruction> instructionList = new ArrayList<>();
        //循环组装获取到的需发送指令

        // 多线程处理
        //初始化线程数量
        CountDownLatch countDownLatch = ThreadUtil.newCountDownLatch(list.size());
        for (MeterReadPo po : list) {
            List<DeviceInstruction> finalInstructionList = instructionList;
            ThreadUtil.execute(() -> {
                List<DeviceInstruction> assembleDeviceInstructionList = this.assembleSendMessage(po);
                if (!CollectionUtils.isEmpty(assembleDeviceInstructionList)) {
                    finalInstructionList.addAll(assembleDeviceInstructionList);
                }
                //调用线程计数器-1
                countDownLatch.countDown();
            });
            if (!CollectionUtils.isEmpty(finalInstructionList)) {
                instructionList.addAll(finalInstructionList);
            }
        }
        //唤醒主线程
        countDownLatch.await();
        instructionList = instructionList.stream()
                .collect(Collectors.toMap(
                        obj -> Arrays.asList(obj.getDtuId(), obj.getAddress(), obj.getInstructType(), obj.getProtocolType()), // 使用多个字段组合作为键
                        obj -> obj,
                        (existing, replacement) -> existing // 如果存在重复，保留第一个
                ))
                .values()
                .stream()
                .collect(Collectors.toList());

        if (!CollectionUtils.isEmpty(instructionList)) {
            instructionList.forEach(deviceInstruction -> deviceInstruction.setBusinessType(businessType));
            deviceInstructionService.batchInsert(instructionList);
        }
    }

    /**
     * 组装发送指令
     *
     * @param po
     * @return
     */
    private List<DeviceInstruction> assembleSendMessage(MeterReadPo po) {
        if (CollectionUtils.isEmpty(po.getEquipmentTypes())) {
            return Lists.newArrayList();
        }
        List<DeviceInstruction> list = new ArrayList<>();
        List<DeviceInstruction> instructionList = new ArrayList<>();
        switch (po.getProtocolType()) {
            case "7":
                //楼栋
                instructionList = this.readBuild(po);
                break;
            case AgreementConstants.AgreementType.UNIT_VALVE :
                //单元阀门
                instructionList = this.readBuildUnit(po);
                break;
            case AgreementConstants.AgreementType.UNIT_HEAT_METER:
                //单元热量表
                instructionList = this.readBuildUnit(po);
                break;
            case AgreementConstants.AgreementType.HOUSEHOLD_VALVE:
                //住户阀门1
                instructionList = this.readHousehold(po);
                break;
            case AgreementConstants.AgreementType.SEAHORSE_VALVE_METER:
                //海龙马阀门
                instructionList = this.readHousehold(po);
                break;
            case AgreementConstants.AgreementType.HOUSEHOLD_HEAT_METER:
                //住户热量表
                instructionList = this.readHousehold(po);
                break;
            default:
                break;
        }
        list.addAll(instructionList);
        return list;
    }

    /**
     * 获取楼栋抄表指令
     *
     * @param po
     * @return 指令集合
     */
    private List<DeviceInstruction> readBuild(MeterReadPo po) {
        //TODO 目前没有楼栋协议，展示返回空数组
        List<DeviceInstruction> list = new ArrayList<>();
        return list;
    }

    /**
     * 获取单元抄表指令
     *
     * @param po
     * @return 指令集合
     */
    private List<DeviceInstruction> readBuildUnit(MeterReadPo po) {
        List<DeviceInstruction> list = new ArrayList<>();
        DeviceInstruction deviceInstruction;
        for (String equipmentType : po.getEquipmentTypes()) {
            switch (equipmentType) {
                case AgreementConstants.EquipmentType.HEAT_METER:
                    //单元热量表
                    Long startTime = DateUtils.getTotalTime();
                    log.info("》》》》》》》》》》》》》单个单元热量表抄表开始时间：" + startTime);
                    List<DeviceInstruction> valveList = this.readBuildUnitHeatMeter(po);
                    Long endTime = DateUtils.getTotalTime();
                    log.info("》》》》》》》》》》》》》单个单元热量表抄表结束时间：" + endTime);
                    log.info("单个单元热量表抄表耗时：" + (endTime - startTime) + "毫秒");
                    if (!CollectionUtils.isEmpty(valveList)) {
                        list.addAll(valveList);
                    }
                    break;
                case AgreementConstants.EquipmentType.VALVE:
                    //单元阀门
                    Long st = DateUtils.getTotalTime();
                    log.info("》》》》》》》》》》》》》单个单元阀门抄表开始时间：" + st);
                    List<DeviceInstruction> unitList = this.readBuildUnitValveMeter(po);
                    Long en = DateUtils.getTotalTime();
                    log.info("》》》》》》》》》》》》》单个单元阀门抄表结束时间：" + en);
                    log.info("单个单元阀门热量表抄表耗时：" + (en - st) + "毫秒");
                    if (!CollectionUtils.isEmpty(unitList)) {
                        list.addAll(unitList);
                    }
                    break;
                default:
                    break;
            }
        }
        return list;
    }

    /**
     * 获取单元热量表抄表指令
     *
     * @param po
     * @return 指令集合
     */
    public List<DeviceInstruction> readBuildUnitHeatMeter(MeterReadPo po) {

        //根据单元id获取单元热量表设备
        List<Equipment> equipmentList = equipmentService.list(Wrappers.lambdaQuery(Equipment.class)
                .eq(Equipment::getUnitId, po.getUnitId())
                .eq(Equipment::getProtocolType, AgreementConstants.AgreementType.UNIT_HEAT_METER)
                .eq(Equipment::getEquipmentLevel, AgreementConstants.DataType.BUILD_UNIT));

        if (CollectionUtils.isEmpty(equipmentList)) {
            return null;
        }

        List<DeviceInstruction> list = Lists.newArrayList();

        DeviceInstruction instruction = new DeviceInstruction();
        AgreementCommand command = agreementCommandService.getSendAgreementCommand(AgreementConstants.AgreementType.UNIT_HEAT_METER, AgreementConstants.InstructionType.SEND, "1");

        String message = "";
        for (Equipment equipment : equipmentList) {
            message = command.getPrefix() + command.getStartChar() + command.getDeviceType() + po.getHeatAddress()
                    + command.getControlCode() + command.getLengthField() + command.getDataFieldInstruct();
            //获取序列号
            AgreementHeatListDto dto = new AgreementHeatListDto();
            dto.setProtocolType(AgreementConstants.AgreementType.UNIT_HEAT_METER);
            dto.setDtuId(equipment.getDtuId());
            dto.setAddress(equipment.getAddress());
            dto.setInstructType("1");
            //获取序列号
//        String ser = FormatData.tenToHexadecimal(Integer.valueOf(heatService.getDataFieldSerialNumber(dto)), 1);
            message += FormatData.tenToHexadecimal(1, 1);
            //获取校验码
            String checkCode = HexadecimalUtil.getCheckCode(message);
            message += checkCode + command.getEndMark();
            //组装DeviceInstruction数据
            instruction.setDtuId(equipment.getDtuId());
            instruction.setProtocolType(AgreementConstants.AgreementType.UNIT_HEAT_METER);
            instruction.setProtocolName(AgreementConstants.AgreementTypeName.UNIT_HEAT_METER);
            instruction.setInstructType(command.getInstructType());
            instruction.setInstructName(command.getInstructName());
            instruction.setPlotId(equipment.getLotId());
            instruction.setBuildId(equipment.getBuildId());
            instruction.setUnitId(equipment.getUnitId());
            instruction.setHouseholdId(equipment.getHouseholdId());
            instruction.setAddress(equipment.getAddress());
            instruction.setInstructionSet(message);
            list.add(instruction);
        }
        return list;
    }


    /**
     * 获取单元阀门抄表指令
     *
     * @param po
     * @return 指令集合
     */
    public List<DeviceInstruction> readBuildUnitValveMeter(MeterReadPo po) {
        //根据单元id获取单元阀门设备
        List<Equipment> equipmentList = equipmentService.list(Wrappers.lambdaQuery(Equipment.class)
                .eq(Equipment::getUnitId, po.getUnitId())
                .eq(Equipment::getProtocolType, AgreementConstants.AgreementType.UNIT_VALVE)
                .eq(Equipment::getEquipmentLevel, AgreementConstants.DataType.BUILD_UNIT));
        if (CollectionUtils.isEmpty(equipmentList)) {
            return null;
        }
        List<DeviceInstruction> list = Lists.newArrayList();

        DeviceInstruction instruction;
        AgreementCommand command = agreementCommandService.getSendAgreementCommand(AgreementConstants.AgreementType.UNIT_VALVE, AgreementConstants.InstructionType.SEND, "1");

        instruction = new DeviceInstruction();
        String message = "";
        for (Equipment equipment : equipmentList) {
            message = command.getPrefix() + command.getStartChar() + command.getDeviceType() + po.getValveAddress()
                    + command.getControlCode() + command.getLengthField() + command.getDataMark();
            message += FormatData.tenToHexadecimal(1, 1);
            //获取校验码
            String checkCode = HexadecimalUtil.getCheckCode(message);
            message += checkCode + command.getEndMark();
            //组装DeviceInstruction数据
            instruction.setDtuId(equipment.getDtuId());
            instruction.setProtocolType(AgreementConstants.AgreementType.UNIT_VALVE);
            instruction.setProtocolName(AgreementConstants.AgreementTypeName.UNIT_VALVE);
            instruction.setInstructType(command.getInstructType());
            instruction.setInstructName(command.getInstructName());
            instruction.setPlotId(equipment.getLotId());
            instruction.setBuildId(equipment.getBuildId());
            instruction.setUnitId(equipment.getUnitId());
            instruction.setAddress(equipment.getAddress());
            instruction.setInstructionSet(message);
            list.add(instruction);
        }

        return list;
    }

    /**
     * 获取住户抄表指令
     *
     * @param po
     * @return 指令集合
     */
    public List<DeviceInstruction> readHousehold(MeterReadPo po) {
        List<DeviceInstruction> list = new ArrayList<>();
        for (String equipmentType : po.getEquipmentTypes()) {
            switch (equipmentType) {
                case AgreementConstants.EquipmentType.HEAT_METER:
                    //户用热量表
                    List<DeviceInstruction> l = this.readHouseholdHeatMeter(po);
                    if (!CollectionUtils.isEmpty(l)) {
                        list.addAll(l);
                    }
                    break;
                case AgreementConstants.EquipmentType.VALVE:
                    //户用阀门
                    List<DeviceInstruction> li = this.readHouseholdValveMeter(po);
                    if (!CollectionUtils.isEmpty(li)) {
                        list.addAll(li);
                    }
                    break;
                case AgreementConstants.EquipmentType.TEMPERATURE_COLLECTOR:
                    //温度采集器
//                    this.roomTemperatureRead(po);
                    break;
                default:
                    break;
            }
        }
        return list;
    }

    /**
     * 室温抄表
     *
     * @param po
     * @return 指令集合
     */
//    private void roomTemperatureRead(MeterReadPo po) {
//        temperatureService.getTemperatureByHouseholdId(po.getHouseholdId());
//    }

    /**
     * 获取户用热量表抄表指令
     *
     * @param po
     * @return 指令集合
     */
    public List<DeviceInstruction> readHouseholdHeatMeter(MeterReadPo po) {

        //根据住户id获取户用热量表设备
        List<Equipment> equipmentList = equipmentService.list(Wrappers.lambdaQuery(Equipment.class)
                .eq(Equipment::getHouseholdId, po.getHouseholdId())
                .eq(Equipment::getProtocolType, AgreementConstants.AgreementType.HOUSEHOLD_HEAT_METER)
                .eq(Equipment::getEquipmentLevel, AgreementConstants.DataType.HOUSEHOLD));
        if (CollectionUtils.isEmpty(equipmentList)) {
            return null;
        }
        AgreementCommand command = agreementCommandService.getSendAgreementCommand(AgreementConstants.AgreementType.HOUSEHOLD_HEAT_METER, AgreementConstants.InstructionType.SEND, "2");
        DeviceInstruction instruction;
        List<DeviceInstruction> list = Lists.newArrayList();
        for (Equipment equipment : equipmentList) {
            instruction = new DeviceInstruction();
            String message = "";
            message = command.getPrefix() + command.getStartChar() + command.getDeviceType() + po.getHeatAddress()
                    + command.getControlCode() + command.getLengthField() + command.getDataFieldInstruct();
            message += FormatData.tenToHexadecimal(1, 1);
            //获取校验码
            String checkCode = HexadecimalUtil.getCheckCode(message);
            message += checkCode + command.getEndMark();
            //组装DeviceInstruction数据
            instruction.setDtuId(po.getHeatDtuId());
            instruction.setProtocolType(AgreementConstants.AgreementType.HOUSEHOLD_HEAT_METER);
            instruction.setProtocolName(AgreementConstants.AgreementTypeName.HOUSEHOLD_HEAT_METER);
            instruction.setInstructType(command.getInstructType());
            instruction.setInstructName(command.getInstructName());
            instruction.setPlotId(equipment.getLotId());
            instruction.setBuildId(equipment.getBuildId());
            instruction.setUnitId(equipment.getUnitId());
            instruction.setHouseholdId(equipment.getHouseholdId());
            instruction.setAddress(equipment.getAddress());
            instruction.setInstructionSet(message);
            list.add(instruction);
        }

        return list;
    }

    /**
     * 获取户用阀门抄表指令
     *
     * @param po
     * @return 指令集合
     */
    public List<DeviceInstruction> readHouseholdValveMeter(MeterReadPo po) {
        //根据住户id获取户用阀门设备
        List<Equipment> equipmentList = equipmentService.list(Wrappers.lambdaQuery(Equipment.class)
                .eq(Equipment::getHouseholdId, po.getHouseholdId())
                .and(wrapper -> wrapper.eq(Equipment::getProtocolType, AgreementConstants.AgreementType.HOUSEHOLD_VALVE)
                        .or()
                        .eq(Equipment::getProtocolType, AgreementConstants.AgreementType.SEAHORSE_VALVE_METER)
                )
                .eq(Equipment::getEquipmentLevel, AgreementConstants.DataType.HOUSEHOLD));
        if (CollectionUtils.isEmpty(equipmentList)) {
            return null;
        }
        List<DeviceInstruction> list = Lists.newArrayList();
        DeviceInstruction instruction;
        for (Equipment equipment : equipmentList) {

            po.setValveAddress(equipment.getAddress());
            po.setValveDtuId(equipment.getDtuId());
            if (equipment.getProtocolType().equals(AgreementConstants.AgreementType.HOUSEHOLD_VALVE)) {
                instruction = this.householdValve(po);
            } else {
                instruction = monitorService.readRegulatingValveValveMeter(po);
            }
            list.add(instruction);
        }

        return list;
    }

    /**
     * 获取户用阀门抄表指令
     *
     * @param po
     * @return 指令集合
     */
    public DeviceInstruction householdValve(MeterReadPo po) {
        DeviceInstruction instruction = new DeviceInstruction();
//        LambdaQueryWrapper<AgreementCommand> commandWrapper = Wrappers.lambdaQuery();
//        commandWrapper.eq(AgreementCommand::getProtocolType, AgreementConstants.AgreementType.HOUSEHOLD_VALVE)
//                .eq(AgreementCommand::getType, AgreementConstants.InstructionType.SEND)
//                .eq(AgreementCommand::getInstructType, 2);
//        AgreementCommand command = agreementCommandService.getOne(commandWrapper);
        AgreementCommand command = agreementCommandService.getSendAgreementCommand(AgreementConstants.AgreementType.HOUSEHOLD_VALVE, AgreementConstants.InstructionType.SEND, "2");
        String message = "";
        message = command.getPrefix() + command.getStartChar() + command.getDeviceType() + po.getValveAddress()
                + command.getControlCode() + command.getLengthField() + command.getDataFieldInstruct();
        //获取序列号
        AgreementUnitValveListDto dto = new AgreementUnitValveListDto();
        dto.setDtuId(po.getValveDtuId());
        dto.setAddress(po.getValveAddress());
        dto.setInstructType("4");
        //获取校验码
        String checkCode = HexadecimalUtil.getCheckCode(message);
        message += checkCode + command.getEndMark();
        //组装DeviceInstruction数据
        instruction.setDtuId(po.getValveDtuId());
        instruction.setProtocolType(AgreementConstants.AgreementType.HOUSEHOLD_VALVE);
        instruction.setProtocolName(AgreementConstants.AgreementTypeName.HOUSEHOLD_VALVE);
        instruction.setInstructType(command.getInstructType());
        instruction.setInstructName(command.getInstructName());
        instruction.setPlotId(po.getPlotId());
        instruction.setBuildId(po.getBuildId());
        instruction.setUnitId(po.getUnitId());
        instruction.setHouseholdId(po.getHouseholdId());
        instruction.setAddress(po.getValveAddress());
        instruction.setInstructionSet(message);
        return instruction;
    }

    /**
     * 获取海龙马调节阀抄表指令
     *
     * @param po
     * @return 指令集合
     */
    public DeviceInstruction readRegulatingValveValveMeter(MeterReadPo po) {
        //判断阀门地址是否为空
        if (StringUtils.isBlank(po.getValveAddress())) {
            throw new ServiceException("自动抄表失败，未绑定阀门设备！");
        }
        DeviceInstruction instruction = new DeviceInstruction();
        LambdaQueryWrapper<AgreementCommand> commandWrapper = Wrappers.lambdaQuery();
        commandWrapper.eq(AgreementCommand::getProtocolType, AgreementConstants.AgreementType.SEAHORSE_VALVE_METER)
                .eq(AgreementCommand::getType, AgreementConstants.InstructionType.SEND)
                .eq(AgreementCommand::getInstructType, 1);
        AgreementCommand command = agreementCommandService.getOne(commandWrapper);
        String message = "";
        message = command.getPrefix() + command.getStartChar() + command.getDeviceType() + po.getValveAddress()
                + command.getControlCode() + command.getLengthField() + command.getDataFieldInstruct();
        //获取序列号
        AgreementSeahorseValveListDto dto = new AgreementSeahorseValveListDto();
        dto.setDtuId(po.getValveDtuId());
        dto.setAddress(po.getValveAddress());
        dto.setInstructType("1");
        //获取序列号
//        String ser = FormatData.tenToHexadecimal(Integer.valueOf(seahorseValveService.getDataFieldSerialNumber(dto)), 1);
        message += FormatData.tenToHexadecimal(1, 1);
        //获取校验码
        String checkCode = HexadecimalUtil.getCheckCode(message);
        message += checkCode + command.getEndMark();
        //组装DeviceInstruction数据
        instruction.setDtuId(po.getValveDtuId());
        instruction.setProtocolType(AgreementConstants.AgreementType.SEAHORSE_VALVE_METER);
        instruction.setProtocolName(AgreementConstants.AgreementTypeName.SEAHORSE_VALVE_METER);
        instruction.setInstructType(command.getInstructType());
        instruction.setInstructName(command.getInstructName());
        instruction.setPlotId(po.getPlotId());
        instruction.setBuildId(po.getBuildId());
        instruction.setUnitId(po.getUnitId());
        instruction.setHouseholdId(po.getHouseholdId());
        instruction.setAddress(po.getValveAddress());
        instruction.setInstructionSet(message);
        return instruction;
    }

    public void oneClickMeter(MeterReadPo po) throws InterruptedException {
        List<MeterReadPo> list = this.getReadPo(po , "2");
        this.meterRead(AgreementConstants.InstructBusinessType.MANUAL_METER_READ, list);
    }

    /**
     * 获取海龙马调节阀抄表指令
     *
     * @param po
     * @param saveType 1：单个维度抄表  2：多个纬度抄表
     * @return 指令集合
     */
    public List<MeterReadPo> getReadPo(MeterReadPo po , String saveType){
        List<MeterReadPo> list = Lists.newArrayList();
        LambdaQueryWrapper<Equipment> equipmentWrapper = Wrappers.lambdaQuery();
        equipmentWrapper.eq(po.getPlotId() != null, Equipment::getLotId, po.getPlotId())
                .eq(po.getBuildId() != null, Equipment::getBuildId, po.getBuildId())
                .eq(po.getUnitId() != null, Equipment::getUnitId, po.getUnitId());
        if(saveType.equals("1")){
            equipmentWrapper.eq(Equipment::getEquipmentLevel, po.getType());;
        }else {
            equipmentWrapper.ge(Equipment::getEquipmentLevel, po.getType());;
        }

        List<String> equipmentTypes = po.getEquipmentTypes();
        List<String> protocolTypes = Lists.newArrayList();
        if (equipmentTypes.contains("1")) {
            protocolTypes.add("4");
            protocolTypes.add("5");
        }
        if (equipmentTypes.contains("2")) {
            protocolTypes.add("1");
            protocolTypes.add("2");
            protocolTypes.add("6");
        }
        equipmentWrapper.in(Equipment::getProtocolType, protocolTypes);
        List<Equipment> equipmentList = equipmentService.list(equipmentWrapper);
        if (CollectionUtils.isEmpty(equipmentList)) {
            return Lists.newArrayList();
        }

        MeterReadPo meterReadPo;
        String protocolType;
        for (Equipment equipment : equipmentList) {
            meterReadPo = new MeterReadPo();
            meterReadPo.setType(po.getType());
            meterReadPo.setProtocolType(equipment.getProtocolType());
            meterReadPo.setPlotId(equipment.getLotId());
            meterReadPo.setBuildId(equipment.getBuildId());
            meterReadPo.setUnitId(equipment.getUnitId());
            meterReadPo.setHouseholdId(equipment.getHouseholdId());
            protocolType = equipment.getProtocolType();
            if (protocolType.equals(AgreementConstants.AgreementType.HOUSEHOLD_HEAT_METER) ||
                    protocolType.equals(AgreementConstants.AgreementType.UNIT_HEAT_METER)) {
                meterReadPo.setHeatDtuId(equipment.getDtuId());
                meterReadPo.setHeatAddress(equipment.getAddress());
                meterReadPo.setEquipmentTypes(Lists.newArrayList("1"));
            } else {
                meterReadPo.setValveDtuId(equipment.getDtuId());
                meterReadPo.setValveAddress(equipment.getAddress());
                meterReadPo.setEquipmentTypes(Lists.newArrayList("2"));
            }
            list.add(meterReadPo);
        }
        return list;
    }

}
